package main

import "fmt"

//跳跃问题，看最后能不能跳到最后一个元素
//辐射问题，看最大的辐射范围能不能辐射到最后一个元素
//感觉这个不太好理解，看这个把
//func canJUmp(nums []int)bool{
//	//先判断只有一个元素的情况，肯定为true
//	if len(nums)<=1{
//		return false
//	}
//	//初始化dp的一个布尔类型的切片,布尔类型默认为false
//	dp:=make([]bool,len(nums))
//	dp[0]=true
//	//当i =len(nums)是就已经是数组的最后一个元素了
//	for i:=1;i<len(nums);i++{
//		//他这个就相当于每个元素看看跳一下能不能为true
//		//可以认真感受一下这个，i在那个元素，然后就用j访问完i位置之前的所有元素。
//		for j:=i-1;j>=0;j--{
//			//按位与，与运算就是全1得1，其他都得0 5&&2=0101&&0010=0000=0
//			if dp[j]&&nums[j]+j>=i{
//				dp[i]=true
//				break
//			}
//
//		}
//	}
//    return dp[len(nums)-1]
//}

//法二 -找到每步最远能跳多少，看辐射范围
//[2,3,1,1,5]
//func canJum(nums []int)bool {
//	n :=len(nums)
//	//初始化条约范围，用双指针表示，start表示当前位置
//	//end表示当前点能跳的最远位置
//	start :=0
//	end :=start +nums[start]
//	//只要end可以指到最后一个元素的位置就成功
//	for end <n-1{
//		//start ==end 说明当前走到了0的位置，a[0]=0绝对的false 返回错误
//		if start ==end {
//			return false
//		}
//		//找到下一个最优的跳跃点
//		for i:=start;i<=end;i++{
//			if maxs(i+nums[i],start+nums[start]){
//				start = i
//			}
//		}
//		//更新start，end
//		//正常情况下，end应该更新到 start+nums[start]新的点的最远跳点
//		temp :=start
//		start =end
//		end =temp +nums[temp]
//	}
//	return true
//}
func canJump(nums []int) bool {
	l := len(nums)
	if l < 1 {
		return false
	}

	// 自己跳自己
	if l == 1 {
		return true
	}

	// 一开始就跳不动了
	if nums[0] == 0 {
		return false
	}

	zero := -1
	for i := l - 2; i >= 0; i-- {
		// 已经有0值了
		if zero > 0 {
			// 可以跳过0值
			if i+nums[i] > zero {
				// 当前0值可以忽略
				zero = -1
				continue
			}


		}

		if nums[i] == 0 {
			zero = i
			continue
		}

	}

	if zero < 0 {
		return true
	}

	return false
}



func maxs(a,b int)bool{
	if a>b {
		return true
	}else{
		return false
	}
}

func main(){
	var s = []int{2,0,1,0,1}
	fmt.Println(canJump(s))
}